/*
 * @Description: 模块管理
 * @Author: wws1993
 * @Date: 2020-11-30 16:27:39
 * @LastEditTime: 2020-12-14 11:00:47
 * @LastEditors: wws1993
 * @FilePath: \TODO-MANAGER\src\components\CalendarViewModule\modal.ts
 */

import lib from '@/lib';
import store from '@/store';

type Dmode = 'month' | 'week' | 'date';
interface DModal {
  /** 是否展示 */
  visible: boolean;
  /** 展示模式：月-month、周-week、日-date */
  mode: Dmode;
  /** 当前展示时间 */
  current: Date;
  /** 日历容器html填充内容 */
  calendarContext: DMonthData[];
  /** 日历绘制中 */
  loading: boolean;
  /** 日历待办过滤 */
  filter: API.params.TodoManageModal.Query;
  /** 筛选是否展示 */
  filterVisible: boolean;
}

interface DActionPayload extends Modal.ActionsFirPayload {
  state: DModal;
}

interface DTodo extends Manage.Instance {
  /** 待办 */
  type: PartCloseType;
}

interface DMonthData {
  date: string;
  day: number;
  events: DTodo[];
  isCurMonth?: boolean;
  isToday?: boolean;
}

/** 时间长度：天 */
const DAYUNIT = 86400000;
/** 待办日历数据拼接 */
const createHtmlForCalendar: {[k: string]: (e: Date, params: API.params.TodoManageModal.Query) => Promise<DMonthData[]>} = {
  month: (date: Date, params: API.params.TodoManageModal.Query) => {
    return new Promise(resolve => {
      const {currentMonthFirstDay, currentMonthFirstDayWeek, maxDate, currentMonthLastDay} = date.calcDependentCode();
      console.log(currentMonthFirstDayWeek);

      params = {
        ...params,
        startTime: new Date(currentMonthFirstDay.getTime() - currentMonthFirstDayWeek * DAYUNIT),
        endTime: new Date(currentMonthLastDay.getTime() + (42 - currentMonthFirstDayWeek + maxDate) * DAYUNIT),
      };

      store.dispatch('checkoutTodoManage', params).then((result: Manage.Instance[]) => {  // 获取符合条件的待办列表
        console.log(result);

        const data = [];

        for (let i = 0; i < currentMonthFirstDayWeek; i++) {          // 月前循环
          const calcDate = new Date(currentMonthFirstDay.getTime() - DAYUNIT * (currentMonthFirstDayWeek - i));
          data.push({
            date: calcDate.format('yyyy-MM-dd'),
            day: calcDate.getDate(),
            events: getTodoForThisDay(calcDate, result),
          });
        }

        for (let i = 0; i < maxDate; i++) {                           // 当月循环
          const calcDate = new Date(currentMonthFirstDay.getTime() + DAYUNIT * i);
          data.push({
            date: calcDate.format('yyyy-MM-dd'),
            day: calcDate.getDate(),
            events: getTodoForThisDay(calcDate, result),
            isCurMonth: true,
            isToday: calcDate.format('yyyy-MM-dd') === new Date().format('yyyy-MM-dd'),
          });
        }

        for (let i = currentMonthFirstDayWeek + maxDate; i < 42; i++) {                    // 月后循环
          const calcDate = new Date(currentMonthFirstDay.getTime() + DAYUNIT * (i - currentMonthFirstDayWeek));
          data.push({
            date: calcDate.format('yyyy-MM-dd'),
            day: calcDate.getDate(),
            events: getTodoForThisDay(calcDate, result),
          });
        }

        resolve(data);
      });
    });
  },
  week: (date: Date, params: API.params.TodoManageModal.Query) => {
    return new Promise((resolve, reject) => {
      resolve([]);
    });
  },
  date: (date: Date, params: API.params.TodoManageModal.Query) => {
    return new Promise((resolve, reject) => {
      resolve([]);
    });
  },
};

/** 获取某天的待办数据 */
const getTodoForThisDay = (date: Date, list: Manage.Instance[]): DTodo[] => {
  const result: DTodo[] = [];

  for (const todo of list) {
    const type = date.isRange(new Date(todo.startTime), new Date(todo.endTime));

    if (type !== 'open') {
      result.push({
        ...todo,
        type,
      });
    }
  }

  return result;
};

export default {
  namespaced: true,
  state: {
    visible: false,
    mode: 'month',
    current: new Date('2020/12/01'),
    calendarContext: [],
    loading: false,
    filter: {},
    filterVisible: false,
  } as DModal,
  mutations: {
    toggleVisible:  (state: any) => state.visible = !state.visible,
    toggleFilterVisible:  (state: any) => state.filterVisible = !state.filterVisible,
    clearCalendarFilter: (state: any) => state.filter = {},
  },
  actions: {
    changeMode({state, dispatch}: DActionPayload, payload: Dmode) {
      state.mode = payload;

      dispatch('render');
    },
    handleNext({state, dispatch}: DActionPayload) {
      if (state.loading) {
        return lib.notify('您太快了~', '', 'warning');
      }

      const handles = {
        date: 'getNextDay',
        week: 'getNextWeek',
        month: 'getNextMonth',
      };

      const func = handles[state.mode] as 'getNextDay' |'getNextWeek' |'getNextMonth';

      state.current = state.current[func]();
      dispatch('render');
    },
    handlePrev({state, dispatch}: DActionPayload) {
      if (state.loading) {
        return lib.notify('您太快了~', '', 'warning');
      }

      const handles = {
        date: 'getPrevDay',
        week: 'getPrevWeek',
        month: 'getPrevMonth',
      };

      const func = handles[state.mode] as 'getPrevDay' |'getPrevWeek' |'getPrevMonth';

      state.current = state.current[func]();
      dispatch('render');
    },
    render({state}: DActionPayload) {
      state.loading = true;

      createHtmlForCalendar[state.mode]?.(state.current, state.filter).then((calcResult: DMonthData[]) => {
        state.calendarContext = calcResult;
        state.loading = false;
      });
    },
  },
};
